package com.java.interview.i设计模式.代理模式;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Random;

/**
 * @Description:
 * @Auther: sixbing  QQ:414409451
 * @Date: 2018/11/4 13:15
 */
public class DynamicProxy implements InvocationHandler {

    //被代理的对象
    Object targetObject;

    /**
     * 获得被代理后的对象
     *
     * @param object 被代理的对象
     * @return 代理后的对象
     */
    public Object getProxyObject(Object object) {
        this.targetObject = object;
        return Proxy.newProxyInstance(
                targetObject.getClass().getClassLoader(), //类加载器
                targetObject.getClass().getInterfaces(),  //获得被代理对象的所有接口
                this);  //this 是InvocationHandler对象
        //loader:一个ClassLoader对象，定义了由哪个ClassLoader对象来生成代理对象进行加载
        //interfaces:一个Interface对象的数组，表示的是我将要给我需要代理的对象提供一组什么接口，
        // 如果我提供了一组接口给它，那么这个代理对象就宣称实现了该接口(多态)，这样我就能调用这组接口中的方法了
        //h:一个InvocationHandler对象，表示的是当我这个动态代理对象在调用方法的时候，
        // 会关联到哪一个InvocationHandler对象上，间接通过invoke来执行
    }

    /**
     * 当用户调用对象中的每个方法时都通过下面的方法执行，方法必须在接口
     * proxy 被代理后的对象
     * method 将要被执行的方法信息（反射）
     * args 执行方法时需要的参数
     */
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //被织入的内容，开始时间
        if (method.getName().equals("add")) {//判断过来的是不是add方法
            long start = System.currentTimeMillis();

            //使用反射在目标对象上调用方法并传入参数

            Object result = method.invoke(targetObject, args);
            lazy();
            //被织入的内容，结束时间
            Long span = System.currentTimeMillis() - start;
            System.out.println("加操作用时：" + span);
            return result;
        } else {
            long start = System.currentTimeMillis();

            //使用反射在目标对象上调用方法并传入参数

            Object result = method.invoke(targetObject, args);
            lazy();
            //被织入的内容，结束时间
            Long span = System.currentTimeMillis() - start;
            System.out.println("其他用时：" + span);
            return result;
        }


    }

    //模拟延时
    public void lazy() {
        try {
            int n = (int) new Random().nextInt(100);
            Thread.sleep(n);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

//---------------------
//    作者：a31081314
//    来源：CSDN
//    原文：https://blog.csdn.net/a31081314/article/details/78722673
//    版权声明：本文为博主原创文章，转载请附上博文链接！
}
